<?php
namespace Phpcmf\Extend;

class Exceptions extends \CodeIgniter\Debug\Exceptions
{

    /**
     * 排除部分错误提示
     */
    public function errorHandler( $severity,  $message,  $file = null,  $line = null, $context = null)
    {
        if (!in_array($severity, [E_NOTICE, E_WARNING])) { //E_WARNING
            throw new \ErrorException($message, 0, $severity, $file, $line);
        }
    }

    /**
     * 错误输出结果
     */
    public function exceptionHandler(\Throwable $exception)
    {

        // Get Exception Info - these are available
        // directly in the template that's displayed.
        $type    = get_class($exception);
        $codes   = $this->determineCodes($exception);
        $code    = $codes[0];
        $exit    = $codes[1];
        $code    = $exception->getCode();
        $message = $exception->getMessage();
        $file    = $exception->getFile();
        $line    = $exception->getLine();
        $trace   = $exception->getTrace();
        $title   = get_class($exception);


        if (empty($message)) {
            $message = '(null)';
        } elseif (strpos($message, 'The action you requested is not allowed') !== false) {
            #$this->_save_error_file('Error', $file, $line, '防跨站验证', 1);
            dr_exit_msg(0, '防跨站提交验证失败');
        } else {
            $this->_save_error_file($title, $file, $line, $message);
        }

        // 开发者模式直接输出错误
        if (IS_DEV) {
            return parent::exceptionHandler($exception);
        }
        // Log it

        // Fire an Event
        $templates_path = $this->viewPath;
        if (empty($templates_path))
        {
            $templates_path = COREPATH.'Views/errors/';
        }

        if (is_cli())
        {
            $templates_path .= 'cli/';
        }
        else
        {
            //header('HTTP/1.1 500 Internal Server Error', true, 500);
            $templates_path .= 'html/';
        }

        $view = $this->determineView($exception, $templates_path);

        if (!IS_ADMIN) {
            // 前端访问屏蔽敏感信息
            $view = 'user_'.$view;
            $message = str_replace([FCPATH, WEBPATH], ['/', '/'], $message);
        }

        // ajax 返回
        if (IS_AJAX) {
            dr_exit_msg(0, $message);
        }

        ob_start();
        include($templates_path.$view);
        $buffer = ob_get_contents();
        ob_end_clean();
        echo $buffer;

        exit();
    }

    private function _save_error_file($title, $file, $line, $message, $is_kz = 0) {

        // 写入错误日志
        $filepath = WRITEPATH.'phperror/'.date('Y-m-d').'.php';
        $newfile = 0;

        $msg = '';
        if (!is_file($filepath) ) {
            $newfile = true;
            $msg .= "<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>\n\n\n";
        }

        if ( $fp = @fopen($filepath, 'ab')) {
            $msg .= date('Y-m-d H:i:s').' --> '.$title."\n";
            $msg .= '文件: '.$file."\n";
            $msg .= '行号: '.$line."\n";
            $msg .= '错误: '.str_replace(PHP_EOL, '<br>', $message)."\n";
            $msg .= json_encode(['html' => $is_kz ? var_export($_POST, true) : self::highlightFile($file, $line)])."\n";
            $msg .= '地址: '.FC_NOW_URL."\n";
            $msg .= "\n\n";
        } else {
            return;
        }

        flock($fp, LOCK_EX);

        for ($written = 0, $length = strlen($msg); $written < $length; $written += $result) {
            if (($result = fwrite($fp, substr($msg, $written))) === false) {
                break;
            }
        }

        flock($fp, LOCK_UN);
        fclose($fp);

        if ($newfile) {
            chmod($filepath, 0777);
        }

        return;
    }
}